home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / xmllib.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  26KB  |  1,070 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import re
  5. import string
  6. import warnings
  7. warnings.warn('The xmllib module is obsolete.  Use xml.sax instead.', DeprecationWarning)
  8. del warnings
  9. version = '0.3'
  10.  
  11. class Error(RuntimeError):
  12.     pass
  13.  
  14. _S = '[ \t\r\n]+'
  15. _opS = '[ \t\r\n]*'
  16. _Name = '[a-zA-Z_:][-a-zA-Z0-9._:]*'
  17. _QStr = '(?:\'[^\']*\'|"[^"]*")'
  18. illegal = re.compile('[^\t\r\n -~\xa0-\xff]')
  19. interesting = re.compile('[]&<]')
  20. amp = re.compile('&')
  21. ref = re.compile('&(' + _Name + '|#[0-9]+|#x[0-9a-fA-F]+)[^-a-zA-Z0-9._:]')
  22. entityref = re.compile('&(?P<name>' + _Name + ')[^-a-zA-Z0-9._:]')
  23. charref = re.compile('&#(?P<char>[0-9]+[^0-9]|x[0-9a-fA-F]+[^0-9a-fA-F])')
  24. space = re.compile(_S + '$')
  25. newline = re.compile('\n')
  26. attrfind = re.compile(_S + '(?P<name>' + _Name + ')(' + _opS + '=' + _opS + '(?P<value>' + _QStr + '|[-a-zA-Z0-9.:+*%?!\\(\\)_#=~]+))?')
  27. starttagopen = re.compile('<' + _Name)
  28. starttagend = re.compile(_opS + '(?P<slash>/?)>')
  29. starttagmatch = re.compile('<(?P<tagname>' + _Name + ')(?P<attrs>(?:' + attrfind.pattern + ')*)' + starttagend.pattern)
  30. endtagopen = re.compile('</')
  31. endbracket = re.compile(_opS + '>')
  32. endbracketfind = re.compile('(?:[^>\'"]|' + _QStr + ')*>')
  33. tagfind = re.compile(_Name)
  34. cdataopen = re.compile('<!\\[CDATA\\[')
  35. cdataclose = re.compile('\\]\\]>')
  36. _SystemLiteral = '(?P<%s>' + _QStr + ')'
  37. _PublicLiteral = '(?P<%s>"[-\'\\(\\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*"|\'[-\\(\\)+,./:=?;!*#@$_%% \n\ra-zA-Z0-9]*\')'
  38. _ExternalId = '(?:SYSTEM|PUBLIC' + _S + _PublicLiteral % 'pubid' + ')' + _S + _SystemLiteral % 'syslit'
  39. doctype = re.compile('<!DOCTYPE' + _S + '(?P<name>' + _Name + ')(?:' + _S + _ExternalId + ')?' + _opS)
  40. xmldecl = re.compile('<\\?xml' + _S + 'version' + _opS + '=' + _opS + '(?P<version>' + _QStr + ')' + '(?:' + _S + 'encoding' + _opS + '=' + _opS + '(?P<encoding>\'[A-Za-z][-A-Za-z0-9._]*\'|"[A-Za-z][-A-Za-z0-9._]*"))?(?:' + _S + 'standalone' + _opS + '=' + _opS + '(?P<standalone>\'(?:yes|no)\'|"(?:yes|no)"))?' + _opS + '\\?>')
  41. procopen = re.compile('<\\?(?P<proc>' + _Name + ')' + _opS)
  42. procclose = re.compile(_opS + '\\?>')
  43. commentopen = re.compile('<!--')
  44. commentclose = re.compile('-->')
  45. doubledash = re.compile('--')
  46. attrtrans = string.maketrans(' \r\n\t', '    ')
  47. _NCName = '[a-zA-Z_][-a-zA-Z0-9._]*'
  48. ncname = re.compile(_NCName + '$')
  49. qname = re.compile('(?:(?P<prefix>' + _NCName + '):)?(?P<local>' + _NCName + ')$')
  50. xmlns = re.compile('xmlns(?::(?P<ncname>' + _NCName + '))?$')
  51.  
  52. class XMLParser:
  53.     attributes = { }
  54.     elements = { }
  55.     __accept_unquoted_attributes = 0
  56.     __accept_missing_endtag_name = 0
  57.     __map_case = 0
  58.     __accept_utf8 = 0
  59.     __translate_attribute_references = 1
  60.     
  61.     def __init__(self, **kw):
  62.         self._XMLParser__fixed = 0
  63.         if 'accept_unquoted_attributes' in kw:
  64.             self._XMLParser__accept_unquoted_attributes = kw['accept_unquoted_attributes']
  65.         
  66.         if 'accept_missing_endtag_name' in kw:
  67.             self._XMLParser__accept_missing_endtag_name = kw['accept_missing_endtag_name']
  68.         
  69.         if 'map_case' in kw:
  70.             self._XMLParser__map_case = kw['map_case']
  71.         
  72.         if 'accept_utf8' in kw:
  73.             self._XMLParser__accept_utf8 = kw['accept_utf8']
  74.         
  75.         if 'translate_attribute_references' in kw:
  76.             self._XMLParser__translate_attribute_references = kw['translate_attribute_references']
  77.         
  78.         self.reset()
  79.  
  80.     
  81.     def __fixelements(self):
  82.         self._XMLParser__fixed = 1
  83.         self.elements = { }
  84.         self._XMLParser__fixdict(self.__dict__)
  85.         self._XMLParser__fixclass(self.__class__)
  86.  
  87.     
  88.     def __fixclass(self, kl):
  89.         self._XMLParser__fixdict(kl.__dict__)
  90.         for k in kl.__bases__:
  91.             self._XMLParser__fixclass(k)
  92.         
  93.  
  94.     
  95.     def __fixdict(self, dict):
  96.         for key in dict.keys():
  97.             if key[:6] == 'start_':
  98.                 tag = key[6:]
  99.                 (start, end) = self.elements.get(tag, (None, None))
  100.                 if start is None:
  101.                     self.elements[tag] = (getattr(self, key), end)
  102.                 
  103.             start is None
  104.             if key[:4] == 'end_':
  105.                 tag = key[4:]
  106.                 (start, end) = self.elements.get(tag, (None, None))
  107.                 if end is None:
  108.                     self.elements[tag] = (start, getattr(self, key))
  109.                 
  110.             end is None
  111.         
  112.  
  113.     
  114.     def reset(self):
  115.         self.rawdata = ''
  116.         self.stack = []
  117.         self.nomoretags = 0
  118.         self.literal = 0
  119.         self.lineno = 1
  120.         self._XMLParser__at_start = 1
  121.         self._XMLParser__seen_doctype = None
  122.         self._XMLParser__seen_starttag = 0
  123.         self._XMLParser__use_namespaces = 0
  124.         self._XMLParser__namespaces = {
  125.             'xml': None }
  126.         if self.elements is XMLParser.elements:
  127.             self._XMLParser__fixelements()
  128.         
  129.  
  130.     
  131.     def setnomoretags(self):
  132.         self.nomoretags = self.literal = 1
  133.  
  134.     
  135.     def setliteral(self, *args):
  136.         self.literal = 1
  137.  
  138.     
  139.     def feed(self, data):
  140.         self.rawdata = self.rawdata + data
  141.         self.goahead(0)
  142.  
  143.     
  144.     def close(self):
  145.         self.goahead(1)
  146.         if self._XMLParser__fixed:
  147.             self._XMLParser__fixed = 0
  148.             del self.elements
  149.         
  150.  
  151.     
  152.     def translate_references(self, data, all = 1):
  153.         if not self._XMLParser__translate_attribute_references:
  154.             return data
  155.         
  156.         i = 0
  157.         while None:
  158.             res = amp.search(data, i)
  159.             if res is None:
  160.                 return data
  161.             
  162.             s = res.start(0)
  163.             res = ref.match(data, s)
  164.             if res is None:
  165.                 self.syntax_error("bogus `&'")
  166.                 i = s + 1
  167.                 continue
  168.             
  169.             i = res.end(0)
  170.             str = res.group(1)
  171.             rescan = 0
  172.             if str[0] == '#':
  173.                 if str[1] == 'x':
  174.                     str = chr(int(str[2:], 16))
  175.                 else:
  176.                     str = chr(int(str[1:]))
  177.                 if data[i - 1] != ';':
  178.                     self.syntax_error("`;' missing after char reference")
  179.                     i = i - 1
  180.                 
  181.             elif all:
  182.                 if str in self.entitydefs:
  183.                     str = self.entitydefs[str]
  184.                     rescan = 1
  185.                 elif data[i - 1] != ';':
  186.                     self.syntax_error("bogus `&'")
  187.                     i = s + 1
  188.                     continue
  189.                 else:
  190.                     self.syntax_error("reference to unknown entity `&%s;'" % str)
  191.                     str = '&' + str + ';'
  192.             elif data[i - 1] != ';':
  193.                 self.syntax_error("bogus `&'")
  194.                 i = s + 1
  195.                 continue
  196.             
  197.             data = data[:s] + str + data[i:]
  198.             if rescan:
  199.                 i = s
  200.                 continue
  201.             i = s + len(str)
  202.             continue
  203.             return None
  204.  
  205.     
  206.     def getnamespace(self):
  207.         nsdict = { }
  208.         for t, d, nst in self.stack:
  209.             nsdict.update(d)
  210.         
  211.         return nsdict
  212.  
  213.     
  214.     def goahead(self, end):
  215.         rawdata = self.rawdata
  216.         i = 0
  217.         n = len(rawdata)
  218.         while i < n:
  219.             if i > 0:
  220.                 self._XMLParser__at_start = 0
  221.             
  222.             if self.nomoretags:
  223.                 data = rawdata[i:n]
  224.                 self.handle_data(data)
  225.                 self.lineno = self.lineno + data.count('\n')
  226.                 i = n
  227.                 break
  228.             
  229.             res = interesting.search(rawdata, i)
  230.             if res:
  231.                 j = res.start(0)
  232.             else:
  233.                 j = n
  234.             if i < j:
  235.                 data = rawdata[i:j]
  236.                 if self._XMLParser__at_start and space.match(data) is None:
  237.                     self.syntax_error('illegal data at start of file')
  238.                 
  239.                 self._XMLParser__at_start = 0
  240.                 if not (self.stack) and space.match(data) is None:
  241.                     self.syntax_error('data not in content')
  242.                 
  243.                 if not (self._XMLParser__accept_utf8) and illegal.search(data):
  244.                     self.syntax_error('illegal character in content')
  245.                 
  246.                 self.handle_data(data)
  247.                 self.lineno = self.lineno + data.count('\n')
  248.             
  249.             i = j
  250.             if i == n:
  251.                 break
  252.             
  253.             if rawdata[i] == '<':
  254.                 if starttagopen.match(rawdata, i):
  255.                     if self.literal:
  256.                         data = rawdata[i]
  257.                         self.handle_data(data)
  258.                         self.lineno = self.lineno + data.count('\n')
  259.                         i = i + 1
  260.                         continue
  261.                     
  262.                     k = self.parse_starttag(i)
  263.                     if k < 0:
  264.                         break
  265.                     
  266.                     self._XMLParser__seen_starttag = 1
  267.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  268.                     i = k
  269.                     continue
  270.                 
  271.                 if endtagopen.match(rawdata, i):
  272.                     k = self.parse_endtag(i)
  273.                     if k < 0:
  274.                         break
  275.                     
  276.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  277.                     i = k
  278.                     continue
  279.                 
  280.                 if commentopen.match(rawdata, i):
  281.                     if self.literal:
  282.                         data = rawdata[i]
  283.                         self.handle_data(data)
  284.                         self.lineno = self.lineno + data.count('\n')
  285.                         i = i + 1
  286.                         continue
  287.                     
  288.                     k = self.parse_comment(i)
  289.                     if k < 0:
  290.                         break
  291.                     
  292.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  293.                     i = k
  294.                     continue
  295.                 
  296.                 if cdataopen.match(rawdata, i):
  297.                     k = self.parse_cdata(i)
  298.                     if k < 0:
  299.                         break
  300.                     
  301.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  302.                     i = k
  303.                     continue
  304.                 
  305.                 res = xmldecl.match(rawdata, i)
  306.                 if res:
  307.                     if not self._XMLParser__at_start:
  308.                         self.syntax_error('<?xml?> declaration not at start of document')
  309.                     
  310.                     (version, encoding, standalone) = res.group('version', 'encoding', 'standalone')
  311.                     if version[1:-1] != '1.0':
  312.                         raise Error('only XML version 1.0 supported')
  313.                     
  314.                     if encoding:
  315.                         encoding = encoding[1:-1]
  316.                     
  317.                     if standalone:
  318.                         standalone = standalone[1:-1]
  319.                     
  320.                     self.handle_xml(encoding, standalone)
  321.                     i = res.end(0)
  322.                     continue
  323.                 
  324.                 res = procopen.match(rawdata, i)
  325.                 if res:
  326.                     k = self.parse_proc(i)
  327.                     if k < 0:
  328.                         break
  329.                     
  330.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  331.                     i = k
  332.                     continue
  333.                 
  334.                 res = doctype.match(rawdata, i)
  335.                 if res:
  336.                     if self.literal:
  337.                         data = rawdata[i]
  338.                         self.handle_data(data)
  339.                         self.lineno = self.lineno + data.count('\n')
  340.                         i = i + 1
  341.                         continue
  342.                     
  343.                     if self._XMLParser__seen_doctype:
  344.                         self.syntax_error('multiple DOCTYPE elements')
  345.                     
  346.                     if self._XMLParser__seen_starttag:
  347.                         self.syntax_error('DOCTYPE not at beginning of document')
  348.                     
  349.                     k = self.parse_doctype(res)
  350.                     if k < 0:
  351.                         break
  352.                     
  353.                     self._XMLParser__seen_doctype = res.group('name')
  354.                     if self._XMLParser__map_case:
  355.                         self._XMLParser__seen_doctype = self._XMLParser__seen_doctype.lower()
  356.                     
  357.                     self.lineno = self.lineno + rawdata[i:k].count('\n')
  358.                     i = k
  359.                     continue
  360.                 
  361.             elif rawdata[i] == '&':
  362.                 if self.literal:
  363.                     data = rawdata[i]
  364.                     self.handle_data(data)
  365.                     i = i + 1
  366.                     continue
  367.                 
  368.                 res = charref.match(rawdata, i)
  369.                 if res is not None:
  370.                     i = res.end(0)
  371.                     if rawdata[i - 1] != ';':
  372.                         self.syntax_error("`;' missing in charref")
  373.                         i = i - 1
  374.                     
  375.                     if not self.stack:
  376.                         self.syntax_error('data not in content')
  377.                     
  378.                     self.handle_charref(res.group('char')[:-1])
  379.                     self.lineno = self.lineno + res.group(0).count('\n')
  380.                     continue
  381.                 
  382.                 res = entityref.match(rawdata, i)
  383.                 if res is not None:
  384.                     i = res.end(0)
  385.                     if rawdata[i - 1] != ';':
  386.                         self.syntax_error("`;' missing in entityref")
  387.                         i = i - 1
  388.                     
  389.                     name = res.group('name')
  390.                     if self._XMLParser__map_case:
  391.                         name = name.lower()
  392.                     
  393.                     if name in self.entitydefs:
  394.                         self.rawdata = rawdata = rawdata[:res.start(0)] + self.entitydefs[name] + rawdata[i:]
  395.                         n = len(rawdata)
  396.                         i = res.start(0)
  397.                     else:
  398.                         self.unknown_entityref(name)
  399.                     self.lineno = self.lineno + res.group(0).count('\n')
  400.                     continue
  401.                 
  402.             elif rawdata[i] == ']':
  403.                 if self.literal:
  404.                     data = rawdata[i]
  405.                     self.handle_data(data)
  406.                     i = i + 1
  407.                     continue
  408.                 
  409.                 if n - i < 3:
  410.                     break
  411.                 
  412.                 if cdataclose.match(rawdata, i):
  413.                     self.syntax_error("bogus `]]>'")
  414.                 
  415.                 self.handle_data(rawdata[i])
  416.                 i = i + 1
  417.                 continue
  418.             else:
  419.                 raise Error('neither < nor & ??')
  420.             break
  421.         if i > 0:
  422.             self._XMLParser__at_start = 0
  423.         
  424.         if end and i < n:
  425.             data = rawdata[i]
  426.             self.syntax_error("bogus `%s'" % data)
  427.             if not (self._XMLParser__accept_utf8) and illegal.search(data):
  428.                 self.syntax_error('illegal character in content')
  429.             
  430.             self.handle_data(data)
  431.             self.lineno = self.lineno + data.count('\n')
  432.             self.rawdata = rawdata[i + 1:]
  433.             return self.goahead(end)
  434.         
  435.         self.rawdata = rawdata[i:]
  436.         if end:
  437.             if not self._XMLParser__seen_starttag:
  438.                 self.syntax_error('no elements in file')
  439.             
  440.             if self.stack:
  441.                 self.syntax_error('missing end tags')
  442.                 while self.stack:
  443.                     self.finish_endtag(self.stack[-1][0])
  444.             
  445.         
  446.  
  447.     
  448.     def parse_comment(self, i):
  449.         rawdata = self.rawdata
  450.         if rawdata[i:i + 4] != '<!--':
  451.             raise Error('unexpected call to handle_comment')
  452.         
  453.         res = commentclose.search(rawdata, i + 4)
  454.         if res is None:
  455.             return -1
  456.         
  457.         if doubledash.search(rawdata, i + 4, res.start(0)):
  458.             self.syntax_error("`--' inside comment")
  459.         
  460.         if rawdata[res.start(0) - 1] == '-':
  461.             self.syntax_error('comment cannot end in three dashes')
  462.         
  463.         if not (self._XMLParser__accept_utf8) and illegal.search(rawdata, i + 4, res.start(0)):
  464.             self.syntax_error('illegal character in comment')
  465.         
  466.         self.handle_comment(rawdata[i + 4:res.start(0)])
  467.         return res.end(0)
  468.  
  469.     
  470.     def parse_doctype(self, res):
  471.         rawdata = self.rawdata
  472.         n = len(rawdata)
  473.         name = res.group('name')
  474.         if self._XMLParser__map_case:
  475.             name = name.lower()
  476.         
  477.         (pubid, syslit) = res.group('pubid', 'syslit')
  478.         if pubid is not None:
  479.             pubid = pubid[1:-1]
  480.             pubid = ' '.join(pubid.split())
  481.         
  482.         if syslit is not None:
  483.             syslit = syslit[1:-1]
  484.         
  485.         j = k = res.end(0)
  486.         if k >= n:
  487.             return -1
  488.         
  489.         if rawdata[k] == '[':
  490.             level = 0
  491.             k = k + 1
  492.             dq = sq = 0
  493.             while k < n:
  494.                 c = rawdata[k]
  495.                 if not sq and c == '"':
  496.                     dq = not dq
  497.                 elif not dq and c == "'":
  498.                     sq = not sq
  499.                 elif sq or dq:
  500.                     pass
  501.                 elif level <= 0 and c == ']':
  502.                     res = endbracket.match(rawdata, k + 1)
  503.                     if res is None:
  504.                         return -1
  505.                     
  506.                     self.handle_doctype(name, pubid, syslit, rawdata[j + 1:k])
  507.                     return res.end(0)
  508.                 elif c == '<':
  509.                     level = level + 1
  510.                 elif c == '>':
  511.                     level = level - 1
  512.                     if level < 0:
  513.                         self.syntax_error("bogus `>' in DOCTYPE")
  514.                     
  515.                 
  516.                 k = k + 1
  517.         
  518.         res = endbracketfind.match(rawdata, k)
  519.         if res is None:
  520.             return -1
  521.         
  522.         if endbracket.match(rawdata, k) is None:
  523.             self.syntax_error('garbage in DOCTYPE')
  524.         
  525.         self.handle_doctype(name, pubid, syslit, None)
  526.         return res.end(0)
  527.  
  528.     
  529.     def parse_cdata(self, i):
  530.         rawdata = self.rawdata
  531.         if rawdata[i:i + 9] != '<![CDATA[':
  532.             raise Error('unexpected call to parse_cdata')
  533.         
  534.         res = cdataclose.search(rawdata, i + 9)
  535.         if res is None:
  536.             return -1
  537.         
  538.         if not (self._XMLParser__accept_utf8) and illegal.search(rawdata, i + 9, res.start(0)):
  539.             self.syntax_error('illegal character in CDATA')
  540.         
  541.         if not self.stack:
  542.             self.syntax_error('CDATA not in content')
  543.         
  544.         self.handle_cdata(rawdata[i + 9:res.start(0)])
  545.         return res.end(0)
  546.  
  547.     __xml_namespace_attributes = {
  548.         'ns': None,
  549.         'src': None,
  550.         'prefix': None }
  551.     
  552.     def parse_proc(self, i):
  553.         rawdata = self.rawdata
  554.         end = procclose.search(rawdata, i)
  555.         if end is None:
  556.             return -1
  557.         
  558.         j = end.start(0)
  559.         if not (self._XMLParser__accept_utf8) and illegal.search(rawdata, i + 2, j):
  560.             self.syntax_error('illegal character in processing instruction')
  561.         
  562.         res = tagfind.match(rawdata, i + 2)
  563.         if res is None:
  564.             raise Error('unexpected call to parse_proc')
  565.         
  566.         k = res.end(0)
  567.         name = res.group(0)
  568.         if self._XMLParser__map_case:
  569.             name = name.lower()
  570.         
  571.         if name == 'xml:namespace':
  572.             self.syntax_error('old-fashioned namespace declaration')
  573.             self._XMLParser__use_namespaces = -1
  574.             if self._XMLParser__seen_doctype or self._XMLParser__seen_starttag:
  575.                 self.syntax_error('xml:namespace declaration too late in document')
  576.             
  577.             (attrdict, namespace, k) = self.parse_attributes(name, k, j)
  578.             if namespace:
  579.                 self.syntax_error('namespace declaration inside namespace declaration')
  580.             
  581.             for attrname in attrdict.keys():
  582.                 if attrname not in self._XMLParser__xml_namespace_attributes:
  583.                     self.syntax_error("unknown attribute `%s' in xml:namespace tag" % attrname)
  584.                     continue
  585.             
  586.             if 'ns' not in attrdict or 'prefix' not in attrdict:
  587.                 self.syntax_error('xml:namespace without required attributes')
  588.             
  589.             prefix = attrdict.get('prefix')
  590.             if ncname.match(prefix) is None:
  591.                 self.syntax_error('xml:namespace illegal prefix value')
  592.                 return end.end(0)
  593.             
  594.             if prefix in self._XMLParser__namespaces:
  595.                 self.syntax_error('xml:namespace prefix not unique')
  596.             
  597.             self._XMLParser__namespaces[prefix] = attrdict['ns']
  598.         elif name.lower() == 'xml':
  599.             self.syntax_error('illegal processing instruction target name')
  600.         
  601.         self.handle_proc(name, rawdata[k:j])
  602.         return end.end(0)
  603.  
  604.     
  605.     def parse_attributes(self, tag, i, j):
  606.         rawdata = self.rawdata
  607.         attrdict = { }
  608.         namespace = { }
  609.         while i < j:
  610.             res = attrfind.match(rawdata, i)
  611.             if res is None:
  612.                 break
  613.             
  614.             (attrname, attrvalue) = res.group('name', 'value')
  615.             if self._XMLParser__map_case:
  616.                 attrname = attrname.lower()
  617.             
  618.             i = res.end(0)
  619.             if attrvalue is None:
  620.                 self.syntax_error("no value specified for attribute `%s'" % attrname)
  621.                 attrvalue = attrname
  622.             elif "'" == "'":
  623.                 pass
  624.             elif not "'" == attrvalue[-1:]:
  625.                 if '"' == '"':
  626.                     pass
  627.                 elif '"' == attrvalue[-1:]:
  628.                     attrvalue = attrvalue[1:-1]
  629.                 elif not self._XMLParser__accept_unquoted_attributes:
  630.                     self.syntax_error("attribute `%s' value not quoted" % attrname)
  631.                 
  632.             res = xmlns.match(attrname)
  633.             if res is not None:
  634.                 ncname = res.group('ncname')
  635.                 None[namespace if not attrvalue else ''] = None
  636.                 if not self._XMLParser__use_namespaces:
  637.                     self._XMLParser__use_namespaces = len(self.stack) + 1
  638.                     continue
  639.                 continue
  640.             
  641.             if '<' in attrvalue:
  642.                 self.syntax_error("`<' illegal in attribute value")
  643.             
  644.             if attrname in attrdict:
  645.                 self.syntax_error("attribute `%s' specified twice" % attrname)
  646.             
  647.             attrvalue = attrvalue.translate(attrtrans)
  648.             attrdict[attrname] = self.translate_references(attrvalue)
  649.         return (attrdict, namespace, i)
  650.  
  651.     
  652.     def parse_starttag(self, i):
  653.         rawdata = self.rawdata
  654.         end = endbracketfind.match(rawdata, i + 1)
  655.         if end is None:
  656.             return -1
  657.         
  658.         tag = starttagmatch.match(rawdata, i)
  659.         if tag is None or tag.end(0) != end.end(0):
  660.             self.syntax_error('garbage in starttag')
  661.             return end.end(0)
  662.         
  663.         nstag = tagname = tag.group('tagname')
  664.         if self._XMLParser__map_case:
  665.             nstag = tagname = nstag.lower()
  666.         
  667.         if not (self._XMLParser__seen_starttag) and self._XMLParser__seen_doctype and tagname != self._XMLParser__seen_doctype:
  668.             self.syntax_error('starttag does not match DOCTYPE')
  669.         
  670.         if self._XMLParser__seen_starttag and not (self.stack):
  671.             self.syntax_error('multiple elements on top level')
  672.         
  673.         (k, j) = tag.span('attrs')
  674.         (attrdict, nsdict, k) = self.parse_attributes(tagname, k, j)
  675.         self.stack.append((tagname, nsdict, nstag))
  676.         if self._XMLParser__use_namespaces:
  677.             res = qname.match(tagname)
  678.         else:
  679.             res = None
  680.         if res is not None:
  681.             (prefix, nstag) = res.group('prefix', 'local')
  682.             if prefix is None:
  683.                 prefix = ''
  684.             
  685.             ns = None
  686.             for t, d, nst in self.stack:
  687.                 if prefix in d:
  688.                     ns = d[prefix]
  689.                     continue
  690.             
  691.             if ns is None and prefix != '':
  692.                 ns = self._XMLParser__namespaces.get(prefix)
  693.             
  694.             if ns is not None:
  695.                 nstag = ns + ' ' + nstag
  696.             elif prefix != '':
  697.                 nstag = prefix + ':' + nstag
  698.             
  699.             self.stack[-1] = (tagname, nsdict, nstag)
  700.         
  701.         attrnamemap = { }
  702.         for key in attrdict.keys():
  703.             attrnamemap[key] = key
  704.         
  705.         if self._XMLParser__use_namespaces:
  706.             nattrdict = { }
  707.             for key, val in attrdict.items():
  708.                 okey = key
  709.                 res = qname.match(key)
  710.                 if res is not None:
  711.                     (aprefix, key) = res.group('prefix', 'local')
  712.                     if self._XMLParser__map_case:
  713.                         key = key.lower()
  714.                     
  715.                     if aprefix is not None:
  716.                         ans = None
  717.                         for t, d, nst in self.stack:
  718.                             if aprefix in d:
  719.                                 ans = d[aprefix]
  720.                                 continue
  721.                         
  722.                         if ans is None:
  723.                             ans = self._XMLParser__namespaces.get(aprefix)
  724.                         
  725.                         if ans is not None:
  726.                             key = ans + ' ' + key
  727.                         else:
  728.                             key = aprefix + ':' + key
  729.                     
  730.                 
  731.                 nattrdict[key] = val
  732.                 attrnamemap[key] = okey
  733.             
  734.             attrdict = nattrdict
  735.         
  736.         attributes = self.attributes.get(nstag)
  737.         if attributes is not None:
  738.             for key in attrdict.keys():
  739.                 if key not in attributes:
  740.                     self.syntax_error("unknown attribute `%s' in tag `%s'" % (attrnamemap[key], tagname))
  741.                     continue
  742.             
  743.             for key, val in attributes.items():
  744.                 if val is not None and key not in attrdict:
  745.                     attrdict[key] = val
  746.                     continue
  747.             
  748.         
  749.         method = self.elements.get(nstag, (None, None))[0]
  750.         self.finish_starttag(nstag, attrdict, method)
  751.         if tag.group('slash') == '/':
  752.             self.finish_endtag(tagname)
  753.         
  754.         return tag.end(0)
  755.  
  756.     
  757.     def parse_endtag(self, i):
  758.         rawdata = self.rawdata
  759.         end = endbracketfind.match(rawdata, i + 1)
  760.         if end is None:
  761.             return -1
  762.         
  763.         res = tagfind.match(rawdata, i + 2)
  764.         if res is None:
  765.             if self.literal:
  766.                 self.handle_data(rawdata[i])
  767.                 return i + 1
  768.             
  769.             if not self._XMLParser__accept_missing_endtag_name:
  770.                 self.syntax_error('no name specified in end tag')
  771.             
  772.             tag = self.stack[-1][0]
  773.             k = i + 2
  774.         else:
  775.             tag = res.group(0)
  776.             if self._XMLParser__map_case:
  777.                 tag = tag.lower()
  778.             
  779.             if self.literal:
  780.                 if not (self.stack) or tag != self.stack[-1][0]:
  781.                     self.handle_data(rawdata[i])
  782.                     return i + 1
  783.                 
  784.             
  785.             k = res.end(0)
  786.         if endbracket.match(rawdata, k) is None:
  787.             self.syntax_error('garbage in end tag')
  788.         
  789.         self.finish_endtag(tag)
  790.         return end.end(0)
  791.  
  792.     
  793.     def finish_starttag(self, tagname, attrdict, method):
  794.         if method is not None:
  795.             self.handle_starttag(tagname, method, attrdict)
  796.         else:
  797.             self.unknown_starttag(tagname, attrdict)
  798.  
  799.     
  800.     def finish_endtag(self, tag):
  801.         self.literal = 0
  802.         if not tag:
  803.             self.syntax_error('name-less end tag')
  804.             found = len(self.stack) - 1
  805.             if found < 0:
  806.                 self.unknown_endtag(tag)
  807.                 return None
  808.             
  809.         else:
  810.             found = -1
  811.             for i in range(len(self.stack)):
  812.                 if tag == self.stack[i][0]:
  813.                     found = i
  814.                     continue
  815.             
  816.             if found == -1:
  817.                 self.syntax_error('unopened end tag')
  818.                 return None
  819.             
  820.         while len(self.stack) > found:
  821.             if found < len(self.stack) - 1:
  822.                 self.syntax_error('missing close tag for %s' % self.stack[-1][2])
  823.             
  824.             nstag = self.stack[-1][2]
  825.             method = self.elements.get(nstag, (None, None))[1]
  826.             if method is not None:
  827.                 self.handle_endtag(nstag, method)
  828.             else:
  829.                 self.unknown_endtag(nstag)
  830.             if self._XMLParser__use_namespaces == len(self.stack):
  831.                 self._XMLParser__use_namespaces = 0
  832.             
  833.             del self.stack[-1]
  834.  
  835.     
  836.     def handle_xml(self, encoding, standalone):
  837.         pass
  838.  
  839.     
  840.     def handle_doctype(self, tag, pubid, syslit, data):
  841.         pass
  842.  
  843.     
  844.     def handle_starttag(self, tag, method, attrs):
  845.         method(attrs)
  846.  
  847.     
  848.     def handle_endtag(self, tag, method):
  849.         method()
  850.  
  851.     
  852.     def handle_charref(self, name):
  853.         
  854.         try:
  855.             if name[0] == 'x':
  856.                 n = int(name[1:], 16)
  857.             else:
  858.                 n = int(name)
  859.         except ValueError:
  860.             self.unknown_charref(name)
  861.             return None
  862.  
  863.         if n <= n:
  864.             pass
  865.         elif not n <= 255:
  866.             self.unknown_charref(name)
  867.             return None
  868.         
  869.         self.handle_data(chr(n))
  870.  
  871.     entitydefs = {
  872.         'lt': '<',
  873.         'gt': '>',
  874.         'amp': '&',
  875.         'quot': '"',
  876.         'apos': ''' }
  877.     
  878.     def handle_data(self, data):
  879.         pass
  880.  
  881.     
  882.     def handle_cdata(self, data):
  883.         pass
  884.  
  885.     
  886.     def handle_comment(self, data):
  887.         pass
  888.  
  889.     
  890.     def handle_proc(self, name, data):
  891.         pass
  892.  
  893.     
  894.     def syntax_error(self, message):
  895.         raise Error('Syntax error at line %d: %s' % (self.lineno, message))
  896.  
  897.     
  898.     def unknown_starttag(self, tag, attrs):
  899.         pass
  900.  
  901.     
  902.     def unknown_endtag(self, tag):
  903.         pass
  904.  
  905.     
  906.     def unknown_charref(self, ref):
  907.         pass
  908.  
  909.     
  910.     def unknown_entityref(self, name):
  911.         self.syntax_error("reference to unknown entity `&%s;'" % name)
  912.  
  913.  
  914.  
  915. class TestXMLParser(XMLParser):
  916.     
  917.     def __init__(self, **kw):
  918.         self.testdata = ''
  919.         XMLParser.__init__(self, **kw)
  920.  
  921.     
  922.     def handle_xml(self, encoding, standalone):
  923.         self.flush()
  924.         print 'xml: encoding =', encoding, 'standalone =', standalone
  925.  
  926.     
  927.     def handle_doctype(self, tag, pubid, syslit, data):
  928.         self.flush()
  929.         print 'DOCTYPE:', tag, repr(data)
  930.  
  931.     
  932.     def handle_data(self, data):
  933.         self.testdata = self.testdata + data
  934.         if len(repr(self.testdata)) >= 70:
  935.             self.flush()
  936.         
  937.  
  938.     
  939.     def flush(self):
  940.         data = self.testdata
  941.         if data:
  942.             self.testdata = ''
  943.             print 'data:', repr(data)
  944.         
  945.  
  946.     
  947.     def handle_cdata(self, data):
  948.         self.flush()
  949.         print 'cdata:', repr(data)
  950.  
  951.     
  952.     def handle_proc(self, name, data):
  953.         self.flush()
  954.         print 'processing:', name, repr(data)
  955.  
  956.     
  957.     def handle_comment(self, data):
  958.         self.flush()
  959.         r = repr(data)
  960.         if len(r) > 68:
  961.             r = r[:32] + '...' + r[-32:]
  962.         
  963.         print 'comment:', r
  964.  
  965.     
  966.     def syntax_error(self, message):
  967.         print 'error at line %d:' % self.lineno, message
  968.  
  969.     
  970.     def unknown_starttag(self, tag, attrs):
  971.         self.flush()
  972.         if not attrs:
  973.             print 'start tag: <' + tag + '>'
  974.         else:
  975.             print 'start tag: <' + tag,
  976.             for name, value in attrs.items():
  977.                 print name + '=' + '"' + value + '"',
  978.             
  979.             print '>'
  980.  
  981.     
  982.     def unknown_endtag(self, tag):
  983.         self.flush()
  984.         print 'end tag: </' + tag + '>'
  985.  
  986.     
  987.     def unknown_entityref(self, ref):
  988.         self.flush()
  989.         print '*** unknown entity ref: &' + ref + ';'
  990.  
  991.     
  992.     def unknown_charref(self, ref):
  993.         self.flush()
  994.         print '*** unknown char ref: &#' + ref + ';'
  995.  
  996.     
  997.     def close(self):
  998.         XMLParser.close(self)
  999.         self.flush()
  1000.  
  1001.  
  1002.  
  1003. def test(args = None):
  1004.     import sys as sys
  1005.     import getopt as getopt
  1006.     time = time
  1007.     import time
  1008.     if not args:
  1009.         args = sys.argv[1:]
  1010.     
  1011.     (opts, args) = getopt.getopt(args, 'st')
  1012.     klass = TestXMLParser
  1013.     do_time = 0
  1014.     for o, a in opts:
  1015.         if o == '-s':
  1016.             klass = XMLParser
  1017.             continue
  1018.         if o == '-t':
  1019.             do_time = 1
  1020.             continue
  1021.     
  1022.     if args:
  1023.         file = args[0]
  1024.     else:
  1025.         file = 'test.xml'
  1026.     if file == '-':
  1027.         f = sys.stdin
  1028.     else:
  1029.         
  1030.         try:
  1031.             f = open(file, 'r')
  1032.         except IOError:
  1033.             msg = None
  1034.             print file, ':', msg
  1035.             sys.exit(1)
  1036.  
  1037.     data = f.read()
  1038.     if f is not sys.stdin:
  1039.         f.close()
  1040.     
  1041.     x = klass()
  1042.     t0 = time()
  1043.     
  1044.     try:
  1045.         if do_time:
  1046.             x.feed(data)
  1047.             x.close()
  1048.         else:
  1049.             for c in data:
  1050.                 x.feed(c)
  1051.             
  1052.             x.close()
  1053.     except Error:
  1054.         msg = None
  1055.         t1 = time()
  1056.         print msg
  1057.         if do_time:
  1058.             print 'total time: %g' % (t1 - t0)
  1059.         
  1060.         sys.exit(1)
  1061.  
  1062.     t1 = time()
  1063.     if do_time:
  1064.         print 'total time: %g' % (t1 - t0)
  1065.     
  1066.  
  1067. if __name__ == '__main__':
  1068.     test()
  1069.  
  1070.